﻿// ---------------------------------------------------------- ----------------------------------------------------------
// <copyright file="TransactionEditorViewModel.cs" company="Concept Architecture">
//   (c) 2010 Muhammad Umer Farooq
// </copyright>
// <summary>
//   Defines the TransactionEditorViewModel type.
// </summary>
// --------------------------------------------------------------------------------------------------------------------

namespace Hisaab.Windows.Client.ViewModel
{
    using System;
    using System.Collections.Generic;
    using System.Collections.ObjectModel;
    using System.Diagnostics.Contracts;
    using System.Linq;
    using System.Windows.Data;
    using Business.Interfaces;
    using Common;
    using Hisaab.Common;

    using Microsoft.Practices.ServiceLocation;

    using Model;

    /// <summary>
    /// Defines the <seealso cref="TransactionEditorViewModel"/> type.
    /// </summary>
    public class TransactionEditorViewModel : ViewModelBase
    {
        /// <summary>
        /// Save command
        /// </summary>
        public static readonly ActiveAwareCommand SaveCommand = new ActiveAwareCommand();

        /// <summary>
        /// Account object
        /// </summary>
        private readonly ITransactionManager _transactionManager;

        /// <summary>
        /// Account manager
        /// </summary>
        private readonly IAccountManager _accountManager;

        /// <summary>
        /// Tag Manager
        /// </summary>
        private readonly ITagManager _tagManager;

        /// <summary>
        /// The Session Manager
        /// </summary>
        private readonly ISession _session;

        /// <summary>
        /// Transaction types
        /// </summary>
        private CollectionView _transactionTypes;

        /// <summary>
        /// Accounts list
        /// </summary>
        private CollectionView _accounts;

        /// <summary>
        /// Selected transaction
        /// </summary>
        private Transaction _selectedTransaction;

        /// <summary>
        /// The tags collection
        /// </summary>
        private ObservableCollection<Tag> _tags;

        /// <summary>
        /// Initializes a new instance of the <see cref="TransactionEditorViewModel"/> class.
        /// </summary>
        /// <param name="transaction">The transaction.</param>
        public TransactionEditorViewModel(Transaction transaction)
            : this(
                ServiceLocator.Current.GetInstance<ITransactionManager>(),
                ServiceLocator.Current.GetInstance<IAccountManager>(),
                ServiceLocator.Current.GetInstance<ITagManager>(),
                ServiceLocator.Current.GetInstance<ISession>(),
                transaction)
        {
        }

        /// <summary>
        /// Initializes a new instance of the <see cref="TransactionEditorViewModel"/> class.
        /// </summary>
        /// <param name="transactionManager">The transaction manager.</param>
        /// <param name="accountManager">The account manager</param>
        /// <param name="tagManager">The tag Manager</param>
        /// <param name="session">The session</param>
        /// <param name="transaction">The transaction.</param>
        public TransactionEditorViewModel(
            ITransactionManager transactionManager,
            IAccountManager accountManager,
            ITagManager tagManager,
            ISession session,
            Transaction transaction)
        {
            Contract.Requires<ArgumentNullException>(transactionManager != null);
            Contract.Requires<ArgumentNullException>(accountManager != null);
            Contract.Requires<ArgumentNullException>(tagManager != null);
            Contract.Requires<ArgumentNullException>(session != null);

            _transactionManager = transactionManager;
            _accountManager = accountManager;
            _tagManager = tagManager;
            _session = session;
            IsNewTransaction = transaction == null;
            SelectedTransaction = transaction ?? new Transaction { Date = DateTime.Today, LinkedTransactionDate = DateTime.Today, Tags = new List<Tag>() };
        }

        /// <summary>
        /// Gets the transactions.
        /// </summary>
        public IEnumerable<Transaction> Transactions
        {
            get
            {
                return _transactionManager
                    .List()
                    .Select(x => x.Map<Business.Entities.Transaction, Transaction>());
            }
        }

        /// <summary>
        /// Gets the Account Types.
        /// </summary>
        public CollectionView TransactionTypes
        {
            get
            {
                if (_transactionTypes == null)
                {
                    var types = new List<KeyValuePair<TransactionTypes, string>>
                                    {
                                        new KeyValuePair<TransactionTypes, string>(Model.TransactionTypes.Expanse, "Expanse"),
                                        new KeyValuePair<TransactionTypes, string>(Model.TransactionTypes.Income, "Income")
                                    };
                    if (IsNewTransaction)
                    {
                        types.Add(new KeyValuePair<TransactionTypes, string>(Model.TransactionTypes.Transfer, "Transfer"));
                    }

                    _transactionTypes = new CollectionView(types);
                }

                return _transactionTypes;
            }
        }

        /// <summary>
        /// Gets the Account Types.
        /// </summary>
        public CollectionView Accounts
        {
            get
            {
                if (_accounts == null)
                {
                    _accounts = new CollectionView(
                        _accountManager
                            .List(new Business.Entities.Account { UserId = _session.LoggedUser })
                            .OrderBy(x => x.Name)
                            .Select(x => x.Map<Business.Entities.Account, Account>()));
                }

                return _accounts;
            }
        }

        /// <summary>
        /// Gets the tags.
        /// </summary>
        public ObservableCollection<Tag> Tags
        {
            get
            {
                if (_tags == null)
                {
                    _tags = new ObservableCollection<Tag>(
                        _tagManager
                            .List(new Business.Entities.Tag { UserId = _session.LoggedUser })
                            .OrderBy(x => x.Name)
                            .Select(x => x.Map<Business.Entities.Tag, Tag>()));
                }

                return _tags;
            }
        }

        /// <summary>
        /// Gets or sets the selected transaction.
        /// </summary>
        /// <value>
        /// The selected transaction.
        /// </value>
        public Transaction SelectedTransaction
        {
            get
            {
                return _selectedTransaction;
            }

            set
            {
                if (_selectedTransaction != value)
                {
                    _selectedTransaction = value;
                    OnPropertyChanged("SelectedTransaction");
                }
            }
        }

        /// <summary>
        /// Gets or sets a value indicating whether [new account].
        /// </summary>
        /// <value>
        /// True if new account; otherwise, false.
        /// </value>
        public bool IsNewTransaction { get; set; }

        /// <summary>
        /// Saves the transaction.
        /// </summary>
        /// <param name="obj">The object</param>
        public void SaveTransaction(object obj)
        {
            if (IsNewTransaction)
            {
                _transactionManager.Add(SelectedTransaction.Map<Transaction, Business.Entities.Transaction>());
            }
            else
            {
                _transactionManager.Update(SelectedTransaction.Map<Transaction, Business.Entities.Transaction>());
            }

            DocumentManager.Instance.CloseCurrent();
        }

        /// <summary>
        /// Determines whether this instance [can save transaction] the specified obj.
        /// </summary>
        /// <param name="obj">The object</param>
        /// <returns>
        /// True if this instance can save transaction the specified obj; otherwise, false.
        /// </returns>
        public bool CanSaveTransaction(object obj)
        {
            return true;
        }
    }
}